package com.zyc.remoting.handler;

import com.zyc.enums.RpcErrorMessageEnum;
import com.zyc.exception.RpcException;
import com.zyc.factory.SingletonFactory;
import com.zyc.provider.impl.ZKServiceProviderImpl;
import com.zyc.remoting.dto.RpcRequest;
import com.zyc.remoting.dto.RpcResponse;
import com.zyc.provider.ServiceProvider;
import com.zyc.provider.impl.ServiceProviderImpl;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * rpc请求处理器
 * @author zyc
 * @create 2022--05--09 17:59
 */
@Slf4j
public class RpcRequestHandler {
    private final ServiceProvider serviceProvider;


    public RpcRequestHandler() {
        serviceProvider = SingletonFactory.getInstance(ZKServiceProviderImpl.class);
    }

    /**
     * 根据请求唤醒正确的服务方法
     * @param rpcRequest
     * @return
     */
    public RpcResponse<Object> handle(RpcRequest rpcRequest) {
        String rpcServiceName = rpcRequest.getRpcServiceName();
        try {
            Object service = serviceProvider.getService(rpcServiceName);
            return invokeTargetMethod(rpcRequest, service);
        } catch (RpcException e) {
            log.info(RpcErrorMessageEnum.SERVICE_CAN_NOT_BE_FOUND.getMessage() + rpcRequest.getMethodName());
            return RpcResponse.fail();
        }
    }

    /**
     *
     * @param rpcRequest 客户端请求
     * @param service 服务端对象
     * @return 目标方法的执行结果
     */
    public RpcResponse<Object> invokeTargetMethod(RpcRequest rpcRequest, Object service) {
        Object result = null;
        RpcResponse<Object> response = null;
        try {
            Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());
            result = method.invoke(service, rpcRequest.getParameters());
            log.info("service:[{}]成功唤醒方法:[{}]", rpcRequest.getRpcServiceName(), rpcRequest.getMethodName());
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            response = RpcResponse.fail();
            log.info("服务调用异常", e);
        }
        response = RpcResponse.success(result, rpcRequest.getRequestId());
        return response;
    }
}
